/**
 * WordTest.java [V 1.0.0]
 * classes : com.xiaocq.iwordkiller.WordTest
 * xiaocq Create at 2012-4-11 下午2:18:07
 */
package com.xiaocq.iwordkiller;

import java.util.Random;
import java.util.TreeSet;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.xiaocq.iwordkiller.db.PrepareCursorHelper;
import com.xiaocq.iwordkiller.file.FileIOHelper;

/**
 * com.xiaocq.iwordkiller.WordTest
 * 
 * @author Mystery Create at 2012-4-11 下午2:18:07
 */
public class WordTest extends Activity implements OnClickListener{
	private static final String TAG = "WordTest";
	private static final String FILE_NAME = "records.txt";
	private static final int MAX_COUNT = 3632;
	private Param mParam;

	private Button mBackToMenu;
	private TextView mProgress;

	private EditText input, display;

	private Button nextOne;
	private Button optionA, optionB, optionC, optionD;

	private TreeSet<Integer> checkSet;
	private Cursor rowIdSet;
	private Cursor testData;
	private int[] records;
	private int[] options;
	private int correctId;
	private int limitCounts;
	private String[] correctWords;
	private String[] explains;
	private String explain;

	private long startTimeInMillis, finishTimeInMillis;
	
	private final Random RNG = new Random();
	private PrepareTask mTask;
	private SaveTask sTask;
	private ProgressDialog progressDialog;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		mParam = new Param(this);
		Intent intent = getIntent();
		mParam.loadFromIntent(intent);
		
		Log.d(TAG, mParam.toString());
		
		mTask = new PrepareTask();
		mTask.execute();

	}
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		save();
	}


	private class PrepareTask extends AsyncTask<Void, Void, Void> {
		private PrepareCursorHelper helper;

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			progressDialog = new ProgressDialog(WordTest.this);
			progressDialog.setMessage(getText(R.string.tip_loading));
			progressDialog.setCancelable(false);
			progressDialog.show();

			helper = new PrepareCursorHelper(WordTest.this);
			helper.open();
		}

		@Override
		protected Void doInBackground(Void... params) {
			if (mParam.testType == Param.CHOICE) {
				rowIdSet = helper.getRowIdSetByTestId(mParam.testId);
				testData = helper.getAllData(Param.ALL);

				limitCounts = rowIdSet.getCount();
			} else {
				testData = helper.getTestDataByTestId(mParam.testId);

				limitCounts = testData.getCount();
			}
			
			if (mParam.isNewTest == false) {
				FileIOHelper fHelper = new FileIOHelper(WordTest.this);
				checkSet = new TreeSet<Integer>();
				records = fHelper.getRecordsFromFile(FILE_NAME, mParam.testCounts);
				int length = records.length;
				for(int i=0; i<length; i++){
					if(records[i] == 0) break;
					checkSet.add(records[i] / 10);
				}
			} else {
				records = new int[mParam.testCounts];
				checkSet = new TreeSet<Integer>();
			}
			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);
			if (mParam.testType == Param.COMPLETION) {
				setContentView(R.layout.completiontest);
				initCompletion();
			} else {
				setContentView(R.layout.choicetest);
				initChoice();
			}

			prepareWords();
			helper.close();
			progressDialog.dismiss();

		}
	}
	
	private void initCompletion() {
		mBackToMenu = (Button) findViewById(R.id.completion_backToMenu); mBackToMenu.setTag(R.string.tip_back);
		mProgress = (TextView) findViewById(R.id.completion_progress);
		input = (EditText) findViewById(R.id.completion_input);
		display = (EditText) findViewById(R.id.completion_display);
		nextOne = (Button) findViewById(R.id.completion_next_one);
		if(mParam.finishedCounts == mParam.testCounts - 1){
			nextOne.setText(R.string.tip_finish);
		}
		
		mBackToMenu.setOnClickListener(this);
		nextOne.setOnClickListener(new OnClickListener() {
			String answer;
			boolean isCorrect = false;
			public void onClick(View v) {
				finishTimeInMillis = System.currentTimeMillis();
				mParam.totalTestTime += (finishTimeInMillis - startTimeInMillis);
				answer = input.getText().toString().trim();
				for(String right : correctWords){
					if(answer.equals(right)){
						isCorrect = true;
						break;
					}
				}
				updateRecord(isCorrect);
				
				if(mParam.finishedCounts == mParam.testCounts - 1){
					checkAndResult();
					return;
				}
				
				mParam.finishedCounts++;
				
				if(mParam.finishedCounts == mParam.testCounts - 1){
					nextOne.setText(R.string.tip_finish);
				}
				prepareWords();
			}
		});
	}

	private void initChoice() {
		mBackToMenu = (Button) findViewById(R.id.choicetest_backToMenu); mBackToMenu.setTag(R.string.tip_back);
		mProgress = (TextView) findViewById(R.id.choicetest_progress);
		display = (EditText) findViewById(R.id.choicetest_display);
		optionA = (Button) findViewById(R.id.choicetest_choiceA);
		optionB = (Button) findViewById(R.id.choicetest_choiceB);
		optionC = (Button) findViewById(R.id.choicetest_choiceC);
		optionD = (Button) findViewById(R.id.choicetest_choiceD);
		
		mBackToMenu.setOnClickListener(this);
		optionA.setOnClickListener(this);
		optionB.setOnClickListener(this);
		optionC.setOnClickListener(this);
		optionD.setOnClickListener(this);
	}

	private void prepareWords() {
		if (records[mParam.finishedCounts] == 0) {
			addNewWord();
		}
		getWords(records[mParam.finishedCounts] / 10);
		mProgress.setText((mParam.finishedCounts + 1) + " / " + mParam.testCounts);
		startTimeInMillis = System.currentTimeMillis();
	}

	private void addNewWord() {
		int rowId;
		int randNumber;
		do {
			randNumber = RNG.nextInt(limitCounts);
		} while (checkSet.contains(randNumber));
		
		checkSet.add(randNumber);

		if (mParam.testType == Param.COMPLETION) {
			records[mParam.finishedCounts] = randNumber * 10;
		} else {
			rowIdSet.moveToPosition(randNumber);
			rowId = rowIdSet.getInt(0);
			records[mParam.finishedCounts] = rowId * 10;
		}
	}

	private void getWords(int rowId) {
		testData.moveToPosition(rowId);
		if (mParam.testType == Param.COMPLETION) {
			input.setText("");
			explain = testData.getString(2).replaceAll("\\|", "\n");
			correctWords = testData.getString(1).split("/");
			display.setText(explain);
		} else {
			prepareOptionsRowId(rowId);
			display.setText(testData.getString(1));
			explains = getOptions(options, correctId);
			optionA.setText(explains[0]); optionA.setTag(options[0]);
			optionB.setText(explains[1]); optionB.setTag(options[1]);
			optionC.setText(explains[2]); optionC.setTag(options[2]);
			optionD.setText(explains[3]); optionD.setTag(options[3]);
		}
	}

	public void prepareOptionsRowId(int rowId) {
		options = new int[4];
		options[0] = rowId;
		correctId = rowId;
		int size = 1;
		int index;
		int randNumber;

out: 	do {
			randNumber = RNG.nextInt(MAX_COUNT);
			for (index = 0; index < size; index++) {
				if (options[index] == randNumber) {
					break out;
				}
			}
			options[size++] = randNumber;
		} while (size < 4);

		changeOrder();
	}

	private void changeOrder() {
		int index = RNG.nextInt(4);
		int tmp;
		for (int i = 0; i < 4; i++) {
			if (correctId == options[i]) {
				tmp = options[i];
				options[i] = options[index];
				options[index] = tmp;
				break;
			}
		}
	}

	private String[] getOptions(int[] options, int correct) {
		String[] results = new String[4];
		String[] allExplains;
		int order;
		for (int i = 0; i < 4; i++) {
			testData.moveToPosition(options[i]);
			allExplains = testData.getString(2).split("\\|");
			order = RNG.nextInt(allExplains.length);
			results[i] = allExplains[order];
		}
		return results;
	}

	public void onClick(View v) {
		
		int which = (Integer) v.getTag();
		boolean isCorrect;
		if(which == R.string.tip_back){
			saveAndBack();
			return;
		}
		finishTimeInMillis = System.currentTimeMillis();
		mParam.totalTestTime += (finishTimeInMillis - startTimeInMillis);
		
		isCorrect = (which == correctId);
		updateRecord(isCorrect);
		
		if(mParam.finishedCounts == mParam.testCounts - 1){
			checkAndResult();
			return;
		}
		
		mParam.finishedCounts++;
		prepareWords();
	}
	
	private void saveAndBack(){
		save();
		Toast.makeText(this, R.string.tip_progressSaved, Toast.LENGTH_SHORT).show();
		finish();
	}
	
	private void save(){
		mParam.isNewTest = false;
		mParam.save();
		FileIOHelper fHelper = new FileIOHelper(this);
		fHelper.writeIntoFile(FILE_NAME, records);
	}
	
	
	private void updateRecord(boolean isCorrect){
		records[mParam.finishedCounts] += (isCorrect ? 1 : 2);
//		Log.d(TAG, "value " + records[mParam.finishedCounts] + " correctId " + correctId);
	}
	
	private void checkAndResult(){
		if(mParam.testType == Param.CHOICE){
			optionA.setEnabled(false);
			optionB.setEnabled(false);
			optionC.setEnabled(false);
			optionD.setEnabled(false);
		}else{
			nextOne.setEnabled(false);
		}
		sTask = new SaveTask();
		sTask.execute();
	}
	
	private class SaveTask extends AsyncTask<Void, Void, Void>{
		private PrepareCursorHelper helper;
		private int wrongCounts;
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			progressDialog.setMessage(getText(R.string.tip_saving));
			progressDialog.show();
			
			mParam.finishTime = System.currentTimeMillis();
			
			helper = new PrepareCursorHelper(WordTest.this);
			helper.open();
		}

		@Override
		protected Void doInBackground(Void... params) {
			wrongCounts = helper.updateDatabase(records, mParam.finishTime);
			return null;
		}
		
		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);
			mParam.setWrongCounts(wrongCounts);
			helper.close();
			
			Intent intent = mParam.getIntentOfParam();
			intent.setClass(WordTest.this, ResultShow.class);
			mParam.initNewParam();
			mParam.save();
			startActivity(intent);
			progressDialog.dismiss();
			finish();

		}
	}
}
